Skip to content

Statements vs. Expressions

When working with React, we're allowed to put expressions in our JSX, but we're not allowed to put statements. Therefore, it's critically important to understand the difference between the two!

Expressions

At its core, an expression is a bit of JavaScript code that produces a value.

For example, these are all expressions:

  • 1 → produces 1
  • "hello" → produces "hello"
  • 5 * 10 → produces 50
  • num > 100 → produces either true or false
  • isHappy ? "🙂" : "🙁" → produces an emoji
  • [1, 2, 3].pop() → produces the number 3

Expressions can contain expressions. For example, how many expressions do you count in this chunk of JS code? Make a guess, and then drag the slider to see them each highlighted:

Statements

A JavaScript program is made up of statements. Each statement is an instruction to the computer to do a particular thing.

Here are some examples of statements in JavaScript:

let hi = 5;
if (hi > 10) {
// More statements here
}
throw new Error('Something exploded!');

Here's how I like to think about this: statements are the rigid structure that holds our program together, while expressions fill in the details.

Statements often have "slots" for expressions. We can put any expression we like into those slots.

For example, declaring a variable has an expression slot:

let hi = /* some expression */;

We can use any of the expressions we saw earlier in that slot:

let hi = 1;
let hi = "hello";
let hi = 5 * 10;
let hi = num > 100;
let hi = isHappy ? "🙂" : "🙁";
let hi = [1, 2, 3].pop();

In terms of valid syntax, expressions are interchangeable. If a statement has an expression slot, we can put any expression there, and the code will run. We won't get a syntax error.

That said, we can still run into other issues. For example, the following code is syntactically valid, but we'll crash the browser tab if we try to run it, since it causes an infinite loop:

while ("hello") {
// Because “hello” never changes, this loop will
// run over and over until the script crashes.
// Syntactically valid, but still problematic.
}

Statements typically end in a semicolon, which marks the end of the statement. If they're omitted, the browser will add them in automatically, before running the code. The semicolon isn't necessary for certain statements, like if statements, while loops, and function declarations.

A handy trick

Want to know whether a chunk of JS is an expression or a statement? Try to log it out!

console.log(/* Some chunk of JS here */);

If it runs, the code is an expression. If you get an error, it's a statement (or, possibly, invalid JS).

As a bonus, we can even see what the expression resolves to, since it'll be printed in the browser console!

This works because all function arguments must be expressions. Expressions produce a value, and that value will be passed into the function. Statements don't produce a value, and so they can't be used as function arguments.

Even as an experienced developer, I rely a ton on console.log. It's a wonderfully versatile tool!

Expressions as statements

Here is an expression: 1 + 2 + 3.

What happens if we create a JS file that includes only this expression? Let's imagine we save the following content as test.js:

1 + 2 + 3

How many statements does this file have? Zero or one?

Here's the deal: expressions can't exist on their own. They're always part of a statement. And so in this case, we have a statement that looks like this:

/* expression slot */;

Every statement is a specific instruction. In this case, this statement tells the computer "Execute the expression in this expression slot".

When we run this code, the expression 1 + 2 + 3 fills this slot, and the computer executes the program, running the expression and producing the number 6.

To drive the point home, here are a collection of statements that each serve a different purpose:

// Statement 1: Create a variable
let hi = /* expression slot */;
// Statement 2: Return a value in a function
return /* expression slot */;
// Statement 3: Loop until the provided expression is falsy
while (/* expression slot */) { }
// Statement 4: Execute the provided expression
/* expression slot */;

Often, tutorials will falsely state that expressions are statements, but this isn't quite right. Expressions and statements are distinct things. But it's possible for a statement to wrap around an expression without providing any additional characters, like wrapping a sandwich in clear shrink wrap.


It can take a while for this distinction to become truly intuitive, but here's the important takeaway:

  • Expressions produce a value. We can log them, assign them to variables, or pass them to functions. We can pop expressions in whenever we see an expression slot.
  • Statements are instructions to do a particular thing, like declaring a variable or running a loop. We can only place statements in very specific places.